/*
 ============================================================================
 Name        : GUI.java
 Author      : Dallas Rosson, Joshua Warner, Tyson Lewis, Ken Norton
 Team        : Bitwise Guys
 ============================================================================
 */
package gui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import java.util.List;
import java.util.Observable;
import java.util.Observer;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.ScrollPaneConstants;

import backend.Cpu;
import backend.KeyBoard;

/**
 * GUI.java
 * 
 * The graphical user interface for use with Process Scheduler.
 * 
 * @author Dallas Rosson, Joshua Warner, Tyson Lewis, Ken Norton
 * @version 1.0, 5/26/2012
 */
@SuppressWarnings("serial")
public class GUI extends JFrame implements Observer, KeyListener {
	
	/**
	 * The number of steps to pass to CPU.
	 */
	private int my_numSteps = 10000;
	
	/**
	 * The main panel.
	 */
	private final JPanel my_mainPanel = new JPanel();
	
	/**
	 * The menu.
	 */
	private final JMenuBar my_menuBar = new JMenuBar();
	
	/**
	 * The process panel.
	 */
	private final JPanel my_processPnl = new JPanel();
	
	/**
	 * The system panel.
	 */
	private final JPanel my_systemPnl = new JPanel();
	
	/**
	 * The system status text area.
	 */
	private final JTextArea my_sysStatTxtArea = new JTextArea();
	
	/**
	 * The shared memory value text area.
	 */
	private final JTextArea my_sharedMemoryValueTxtArea = new JTextArea();
	
	/**
	 * The mutex owner text area.
	 */
	private final JTextArea my_mutextOwnerTxtArea = new JTextArea();
	
	/**
	 * The mutex waiting text area.
	 */
	private final JTextArea my_mutexWaitingTxtArea = new JTextArea();
	
	/**
	 * The monitor queue text area.
	 */
	private final JTextArea my_monitorQueueTxtArea = new JTextArea();
	
	/**
	 * The keyboard queue text area.
	 */
	private final JTextArea my_keyboardQueueTxtArea = new JTextArea();
	
	/**
	 * The ready queue text area.
	 */
	private final JTextArea my_readyQueueTxtArea = new JTextArea();
	
	/**
	 * The disk queue text area.
	 */
	private final JTextArea my_diskQueueTxtArea = new JTextArea();
	
	/**
	 * The process text area.
	 */
	private final JTextArea my_processTxtArea = new JTextArea();
	
	/**
	 * The run cpu thread.
	 */
	private ExecutorService my_executor = Executors.newFixedThreadPool(1);
	
	/**
	 * The process list.
	 */
	private List<String> my_processList = new ArrayList<String>();
	
	/**
	 * The preset process list.
	 */
	private final List<String> my_premadeProcessList = new ArrayList<String>();
	
	/**
	 * The steps input field.
	 */
	JTextField my_stepsTxt = new JTextField();
	
	/**
	 * The CPU.
	 */
	private Cpu my_cpu;
	
	/**
	 * The process switch case.
	 */
	private int my_processSwitch = -1;	

	/**
	 * GUI constructor.
	 */
	public GUI() {
		
		createPresetProcessList();
		
		my_cpu = new Cpu(my_numSteps, my_premadeProcessList);
		
	}
	
	
	/**
	 * Initializes the GUI.
	 */
	public void initialize() {
		
        this.setPreferredSize(new Dimension(750, 600));
        this.setResizable(false);
        this.setVisible(true);
        this.setTitle("Process Scheduler");
        this.setIconImage(new ImageIcon("src/gui/mobus.jpg").getImage());
        this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        this.addKeyListener(this);
                
        this.setLayout(new BorderLayout());
        
        my_stepsTxt.setText("10000");
        
        my_mainPanel.setLayout(new BorderLayout());
        
        createMenu();
        createProcessWindow();
        createSystemWindow();        
        
        JPanel windowPanel = new JPanel();
        windowPanel.setLayout(new BorderLayout());
        
        my_processPnl.setPreferredSize(new Dimension(250, 750));
        my_systemPnl.setPreferredSize(new Dimension(350, 750));
        
        windowPanel.add(BorderLayout.WEST, my_processPnl);
        windowPanel.add(BorderLayout.CENTER, my_systemPnl);
        
        my_mainPanel.add(BorderLayout.CENTER, windowPanel);
        
        this.add(BorderLayout.CENTER, my_mainPanel);
        this.pack();
		
	}

	// Component initializers.
	
	/**
	 * Creates the menu and various submenu items.
	 */
	private void createMenu() {
		
		JMenu fileMenu = new JMenu("File");
		JMenu runMenu = new JMenu("Run");
		JMenu helpMenu = new JMenu("Help");
		
		// File menu items.
		JMenu loadListMI = new JMenu("Load Preset Process List");
		JMenuItem loadListMI_list1 = new JMenuItem("Preset Process List 1");
		JMenuItem exitMI = new JMenuItem("Exit");
		
		loadListMI_list1.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(final ActionEvent the_e) {
				
				my_processList.clear();
				my_premadeProcessList.clear();
				
				createPresetProcessList();
				
				for (String s : my_premadeProcessList) {
					
					my_processList.add(s);
				}
				
				my_processTxtArea.setText("");
				
				for (int i = 0; i < my_processList.size() - 1; i++) {
					
					my_processTxtArea.append(my_processList.get(i) + "\n");
				}
			}
		});
		
		exitMI.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(final ActionEvent the_e) {
				
				System.exit(0);
				
			}
		});
		
		loadListMI.add(loadListMI_list1);
		
		fileMenu.add(loadListMI);
		fileMenu.add(exitMI);
		
		// Run menu items.
		JMenuItem startMI = new JMenuItem("Start");
		JMenuItem stopMI = new JMenuItem("Stop");
		
		startMI.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(final ActionEvent the_e) {

				my_sysStatTxtArea.append("Starting program...\n");
				
				my_numSteps = Integer.parseInt(my_stepsTxt.getText());
				
				if (my_numSteps <= 0) {
					
					my_numSteps = 1;
				}
				
				my_cpu = new Cpu(my_numSteps, my_processList);
				my_cpu.addObserver(GUI.this);
				my_executor.execute(my_cpu);
				my_stepsTxt.requestFocus();
			}
		});
		
		stopMI.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(final ActionEvent the_e) {

				my_sysStatTxtArea.append("Stopping program...\n");
				my_cpu.stopCPU();
				my_executor.shutdownNow();
				
			}
		});
		
		runMenu.add(startMI);
		runMenu.add(stopMI);
		
		// Help menu items.
		JMenuItem readMeMI = new JMenuItem("Read Me...");
		JMenuItem aboutMI = new JMenuItem("About...");
		
		aboutMI.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(final ActionEvent the_e) {
            	
            	ImageIcon icon = new ImageIcon("src/gui/mobus.jpg");
                
                JOptionPane.showMessageDialog(my_mainPanel, 
                        "A process scheduler simulation.\n\n" +		
                        "Team: Bitwise Guys\n" +
                        "Author: Ken Norton\n" +
                        "Author: Tyson Lewis\n" +
                        "Author: Dallas Rosson\n" +
                        "Author: Josh Warner\n" +
                        "Version: 1.0", 
                        "About", JOptionPane.INFORMATION_MESSAGE, 
                        icon);
            }
        });
		
		readMeMI.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(final ActionEvent the_e) {
                
                JFrame readMeFrame = new JFrame();
                readMeFrame.setDefaultCloseOperation(DISPOSE_ON_CLOSE);

                JEditorPane readMeEditorPane = new JEditorPane();
                readMeEditorPane.setContentType("text/html");;
                
                readMeFrame.setTitle("Read Me");
                readMeFrame.setLayout(new BorderLayout());
                readMeFrame.setPreferredSize(new Dimension(500, 500));
                readMeFrame.setResizable(true);
                
                JScrollPane scrollPane = new JScrollPane(readMeEditorPane);
                scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
                
                readMeFrame.add(BorderLayout.CENTER, scrollPane);
                
                readMeEditorPane.setText(createReadMeText());
                readMeEditorPane.setCaretPosition(0);
                
                readMeFrame.pack();
                readMeFrame.setVisible(true);
                
                
            }
        });  
		
		helpMenu.add(readMeMI);
		helpMenu.add(aboutMI);
		
		
		// Add to menu bar.
		
		my_menuBar.add(fileMenu);
		my_menuBar.add(runMenu);
		my_menuBar.add(helpMenu);
		
		// Add to main panel.
		
		this.add(BorderLayout.NORTH, my_menuBar);
		
	}
	
	/**
	 * Creates and fills in the process window components.
	 */
	private void createProcessWindow() {
		
		my_processPnl.setPreferredSize(new Dimension(250, 700));
		my_processPnl.setLayout(new BorderLayout());
				
		// Process Radio Buttons
		
		JRadioButton uiRbtn = new JRadioButton("UI Process");
		JRadioButton producerRBtn = new JRadioButton("Producer Process");
		JRadioButton consumerRBtn = new JRadioButton("Consumer Process");
		JRadioButton calculatorRBtn = new JRadioButton("Calculator Process");
		
		uiRbtn.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(final ActionEvent the_e) {

				my_processSwitch = 0;
				
			}
		});
		
		producerRBtn.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(final ActionEvent the_e) {

				my_processSwitch = 1;
				
			}
		});
		
		consumerRBtn.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(final ActionEvent the_e) {

				my_processSwitch = 2;
				
			}
		});
		
		calculatorRBtn.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(final ActionEvent the_e) {

				my_processSwitch = 3;
				
			}
		});

		
		// Create button group and add radio buttons.
		
		ButtonGroup procRBtnGrp = new ButtonGroup();
		
		procRBtnGrp.add(uiRbtn);
		procRBtnGrp.add(producerRBtn);
		procRBtnGrp.add(consumerRBtn);
		procRBtnGrp.add(calculatorRBtn);
		
		// Add radio buttons to their own panel.
		
		JPanel radBtnPnl = new JPanel();
		
		radBtnPnl.setLayout(new GridLayout(5, 1));
		radBtnPnl.setPreferredSize(new Dimension(250, 160));
		radBtnPnl.setBorder(BorderFactory.createLineBorder(Color.black));
		radBtnPnl.add(uiRbtn);
		radBtnPnl.add(producerRBtn);
		radBtnPnl.add(consumerRBtn);
		radBtnPnl.add(calculatorRBtn);
		
		// Create process text window.
		
		JLabel processLbl = new JLabel("Processes");
		processLbl.setBorder(BorderFactory.createLineBorder(Color.black));
		processLbl.setPreferredSize(new Dimension(250, 25));
		
		my_processTxtArea.setBorder(BorderFactory.createLineBorder(Color.black));
		my_processTxtArea.setEditable(false);
		
		JScrollPane scrollProcessTxt = new JScrollPane(my_processTxtArea);
		scrollProcessTxt.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
		
		JPanel processTxtPnl = new JPanel();
		processTxtPnl.setLayout(new BorderLayout());
		
		processTxtPnl.add(BorderLayout.NORTH, processLbl);
		processTxtPnl.add(BorderLayout.CENTER, scrollProcessTxt);
		
		// Create add button.
		
		JButton addProccessBtn = new JButton("Add Process");
		
		addProccessBtn.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(final ActionEvent the_e) {

				switch (my_processSwitch) {
				
				case 0: // Add UI process to queue.
					
					my_processTxtArea.append("ui\n");
					my_processList.add("ui");
				    break;
				        
				case 1: // Add producer process to queue.
					
					my_processTxtArea.append("producer\n");
					my_processList.add("producer");
					break;
					
				case 2: // Add consumer process to queue.
					
					my_processTxtArea.append("consumer\n");
					my_processList.add("consumer");
					break;
					
				case 3: // Add calculator process to queue.
					
					my_processTxtArea.append("calculator\n");
					my_processList.add("calculator");
					break;
					
			    default: // Do nothing.				
				
				}				
			}
		});
		
		JPanel addProcessBtnPnl = new JPanel();
		addProccessBtn.setBorder(BorderFactory.createLineBorder(Color.black));
		addProcessBtnPnl.add(addProccessBtn);
		radBtnPnl.add(addProcessBtnPnl);

		JPanel stepsPnl = new JPanel();
		stepsPnl.setLayout(new BorderLayout());
		stepsPnl.add(BorderLayout.NORTH, new JLabel("Maximum Number of Steps"));
	    stepsPnl.add(BorderLayout.CENTER, my_stepsTxt);
		
		// Add all to the process window.
		
		my_processPnl.add(BorderLayout.NORTH, radBtnPnl);
		my_processPnl.add(BorderLayout.CENTER, processTxtPnl);	
		my_processPnl.add(BorderLayout.SOUTH, stepsPnl);
		
	}
	
	/**
	 * Creates and fills in the system window components.
	 */
	private void createSystemWindow() {
		
		my_systemPnl.setLayout(new BorderLayout());
		
		// Create label for system status.
		
		JLabel sysStatLbl = new JLabel("System Status");
		sysStatLbl.setBorder(BorderFactory.createLineBorder(Color.black));
		sysStatLbl.setPreferredSize(new Dimension(325, 25));
		sysStatLbl.setBorder(BorderFactory.createLineBorder(Color.black));
		
		my_systemPnl.add(BorderLayout.NORTH, sysStatLbl);
		
		// Create text area.
		
		my_sysStatTxtArea.setEditable(false);
		my_sysStatTxtArea.setBorder(BorderFactory.createLineBorder(Color.black));
		
		JScrollPane scrollTxtArea = new JScrollPane(my_sysStatTxtArea);
		scrollTxtArea.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
		
		my_systemPnl.add(BorderLayout.CENTER, scrollTxtArea);
		
		// Create system display.
		
		JPanel sysDisplayPnl = new JPanel();
		sysDisplayPnl.setPreferredSize(new Dimension(325, 225));
		sysDisplayPnl.setLayout(new GridLayout(7, 2));
		
		Dimension sysDisLblDim = new Dimension(75, 25);
		
		JLabel sharedMemLbl = new JLabel("Shared Memory Value:");
		JLabel mutexOwnerLbl = new JLabel("Mutext Owner:");
		JLabel mutextWaitingLbl = new JLabel("Mutex Waiting:");
		JLabel monitorQueueLbl = new JLabel("Monitor Queue:");
		JLabel keyboardQueueLbl = new JLabel("Keyboard Queue:");
		JLabel readyQueueLbl = new JLabel("Ready Queue:");
		JLabel diskQueueLbl = new JLabel("Disk Queue:");
		
		sharedMemLbl.setPreferredSize(sysDisLblDim);
		mutexOwnerLbl.setPreferredSize(sysDisLblDim);
		mutextWaitingLbl.setPreferredSize(sysDisLblDim);
		monitorQueueLbl.setPreferredSize(sysDisLblDim);
		keyboardQueueLbl.setPreferredSize(sysDisLblDim);
		readyQueueLbl.setPreferredSize(sysDisLblDim);
		diskQueueLbl.setPreferredSize(sysDisLblDim);
		
		Dimension sysDisTxtDim = new Dimension(275, 25);
		
		my_sharedMemoryValueTxtArea.setPreferredSize(sysDisTxtDim);
		my_mutextOwnerTxtArea.setPreferredSize(sysDisTxtDim);
		my_mutexWaitingTxtArea.setPreferredSize(sysDisTxtDim);
		my_monitorQueueTxtArea.setPreferredSize(sysDisTxtDim);
		my_keyboardQueueTxtArea.setPreferredSize(sysDisTxtDim);
		my_readyQueueTxtArea.setPreferredSize(sysDisTxtDim);
		my_diskQueueTxtArea.setPreferredSize(sysDisTxtDim);
		
		my_sharedMemoryValueTxtArea.setEditable(false);
		my_mutextOwnerTxtArea.setEditable(false);
		my_mutexWaitingTxtArea.setEditable(false);
		my_monitorQueueTxtArea.setEditable(false);
		my_keyboardQueueTxtArea.setEditable(false);
		my_readyQueueTxtArea.setEditable(false);
		my_diskQueueTxtArea.setEditable(false);
		
		my_sharedMemoryValueTxtArea.setBorder(BorderFactory.createLineBorder(Color.black));
		my_mutextOwnerTxtArea.setBorder(BorderFactory.createLineBorder(Color.black));
		my_mutexWaitingTxtArea.setBorder(BorderFactory.createLineBorder(Color.black));
		my_monitorQueueTxtArea.setBorder(BorderFactory.createLineBorder(Color.black));
		my_keyboardQueueTxtArea.setBorder(BorderFactory.createLineBorder(Color.black));
		my_readyQueueTxtArea.setBorder(BorderFactory.createLineBorder(Color.black));
		my_diskQueueTxtArea.setBorder(BorderFactory.createLineBorder(Color.black));
		
		
		sysDisplayPnl.add(sharedMemLbl);
		sysDisplayPnl.add(my_sharedMemoryValueTxtArea);
		sysDisplayPnl.add(mutexOwnerLbl);
		sysDisplayPnl.add(my_mutextOwnerTxtArea);
		sysDisplayPnl.add(mutextWaitingLbl);
		sysDisplayPnl.add(my_mutexWaitingTxtArea);
		sysDisplayPnl.add(monitorQueueLbl);
		sysDisplayPnl.add(my_monitorQueueTxtArea);
		sysDisplayPnl.add(keyboardQueueLbl);
		sysDisplayPnl.add(my_keyboardQueueTxtArea);
		sysDisplayPnl.add(readyQueueLbl);
		sysDisplayPnl.add(my_readyQueueTxtArea);
		sysDisplayPnl.add(diskQueueLbl);
		sysDisplayPnl.add(my_diskQueueTxtArea);

		my_stepsTxt.addKeyListener(this);
		
		// Create system buttons.
		
		Dimension btnDimension = new Dimension(75, 25);
		
		JButton sysStartBtn = new JButton("Start");		
		JButton sysStopBtn = new JButton("Stop");
		JButton sysExitBtn = new JButton("Exit");
		
		sysStartBtn.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(final ActionEvent the_e) {

				my_sysStatTxtArea.append("Starting program...\n");
				
				my_numSteps = Integer.parseInt(my_stepsTxt.getText());
				
				if (my_numSteps <= 0) {
					
					my_numSteps = 1;
				}
				
				my_cpu = new Cpu(my_numSteps, my_processList);
				my_cpu.addObserver(GUI.this);
				my_executor.execute(my_cpu);
				my_stepsTxt.requestFocus();
			}
		});
		
		sysStopBtn.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(final ActionEvent the_e) {

				my_sysStatTxtArea.append("Stopping program...\n");
				my_cpu.stopCPU();
				my_executor.shutdownNow();
				
			}
		});
		
		sysExitBtn.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(final ActionEvent the_e) {
				
				System.exit(0);
			}
		});		
		
		sysStartBtn.setPreferredSize(btnDimension);
		sysStopBtn.setPreferredSize(btnDimension);
		sysExitBtn.setPreferredSize(btnDimension);
		
		JPanel sysBtnPnl = new JPanel();
		sysBtnPnl.setPreferredSize(new Dimension(325, 50));
		
		sysBtnPnl.add(sysStartBtn);
		sysBtnPnl.add(sysStopBtn);
		sysBtnPnl.add(sysExitBtn);
		
		JPanel sysSouthPnl = new JPanel();
		sysSouthPnl.setPreferredSize(new Dimension(350, 275));
		
		sysSouthPnl.add(BorderLayout.CENTER, sysDisplayPnl);
		sysSouthPnl.add(BorderLayout.SOUTH, sysBtnPnl);
		
		my_systemPnl.add(BorderLayout.SOUTH, sysSouthPnl);
		
	}
	
	// Helpers
	
	public String createReadMeText() {
		StringBuilder sb = new StringBuilder();
		
        sb.append("<b><big>Read Me</b></big>");
        sb.append("<br><br>**********************************************************");
        sb.append("<br><b>General</b>");        
        sb.append("<br>**********************************************************");
        sb.append("<br><br>This program simulates process scheduling in a computer.");
        sb.append("<br><br>Team: Bitwise Guys");
        sb.append("<br>Version: 1.0, 5/29/2012");
        sb.append("<br><br>**********************************************************");
        sb.append("<br><b>Program Run Options</b>");        
        sb.append("<br>**********************************************************");
        sb.append("<br><br><b>1. To add a process:</b> Click on the radio button next to the desired process");
        sb.append("<br>then click the Add button. You can also choose to run a set of preloaded process");
        sb.append("<br> lists.  To do this, click the File menu, then Load List, then select the list");
        sb.append("<br> that you desire to run.");
        sb.append("<br><br><b>2. To set the number of steps:</b> Enter the desired number in the text input window below the process text area.");
        sb.append("<br><br><b>3. To run the processes:</b> Click the Start button or the Start option in the Run menu.");
        sb.append("<br><br><b>4. To stop the program:</b> Click the Stop button or the Stop option in the Run menu.");
        sb.append("<br><br><b>5. To close the program:</b> Click the Exit button or the Exit option in the File menu.");
        sb.append("<br><br><b>6. For keyboard interrupt:</b> Click in the maximum number of steps text field and then procede to hit keys while the program is running.");
        sb.append("<br><br>**********************************************************");
        sb.append("<br><b>And Just for Fun: Klingon Programmers</b>");        
        sb.append("<br>**********************************************************");
        sb.append("<br><br>1. Defensive programming? Never! Klingon programs are always on the offense. Yes, offensive programming is what we do best.");
        sb.append("<br>2. Specifications are for the weak and timid! ");
        sb.append("<br>3. This machine is GAGH! I need dual Pentium processors if I am to do battle with this code!");
        sb.append("<br>4. You cannot really appreciate Dilbert unless you've read it in the original Klingon.");
        sb.append("<br>5. Indentation?! - I will show you how to indent when I indent your skull!");
        sb.append("<br>6. What is this talk of 'release'? Klingons do not make software 'releases'. Our software 'escapes' leaving a bloody trail of designers and quality assurance people in its wake.");
        sb.append("<br>7. Klingon function calls do not have 'parameters' - they have 'arguments' -- and they ALWAYS WIN THEM.");
        sb.append("<br>8. Debugging? Klingons do not debug. Our software does not coddle the weak. Bugs are good for building character in the user.");
        sb.append("<br>9. I have challenged the entire ISO-9000 quality assurance team to a Bat-Leth contest on the holodeck. They will not concern us again.");
        sb.append("<br>10. A TRUE Klingon Warrior does not comment his code!");
        sb.append("<br>11. By filing this bug report you have challenged the honor of my family. Prepare to die!");
        sb.append("<br>12. You question the worthiness of my code? I should kill you where you stand!");
        sb.append("<br>13. Our users will know fear and cower before our software! Ship it! Ship it and let them flee like the dogs they are!");
        sb.append("<br>14. Our competitors (the Cougars) are without honor!");
        sb.append("<br>15. Java? That is for children. A Klingon Warrior uses only machine code, keyed in on the front panel switches in raw binary.");
        sb.append("<br>16. Klingon programs don't do accountancy. For that, you need a Ferengi.");
        sb.append("<br>17. Klingon multitasking systems do not support time-sharing. When a Klingon program wants to run, it challenges the scheduler in hand-to-hand combat and owns the machine.");
        sb.append("<br>18. Perhaps it IS a good day to die! I say we ship it!");
        sb.append("<br>19. My program has just dumped Stova Core!");
        sb.append("<br>20. Behold, the keyboard of Ge'Org Moh'Bus! The greatest Klingon code warrior that ever lived!");
        	
		return sb.toString();
	}
	
	/**
	 * Updates the GUI text areas to reflect the current state of the program.
	 * 
	 * @param the_o The observable object.
	 */
	public void update(final Observable the_o, Object the_text) {
		
		// Update various text fields with stuff from mobo.
		
		//System.out.println("In update....");
		
		if (the_text instanceof String) {
			
			my_sysStatTxtArea.append((String) the_text + "\n");
		}
		
		my_sharedMemoryValueTxtArea.setText(my_cpu.getSharedMemoryValue());
		my_mutextOwnerTxtArea.setText(my_cpu.getMutexOwner());
		my_mutexWaitingTxtArea.setText(my_cpu.getMutexWaitList());
		my_monitorQueueTxtArea.setText(my_cpu.getMonitorQ());
		my_keyboardQueueTxtArea.setText(my_cpu.getKeyboardQ());
		my_readyQueueTxtArea.setText(my_cpu.getReadyQ());
		my_diskQueueTxtArea.setText(my_cpu.getDiscQ());
	}
	
	/**
	 * Creates the preset process list.
	 */
	private void createPresetProcessList() {
		
		my_premadeProcessList.add("ui");
		my_premadeProcessList.add("consumer");
		my_premadeProcessList.add("consumer");
		my_premadeProcessList.add("producer");
		my_premadeProcessList.add("calculator");
		my_premadeProcessList.add("producer");
		my_premadeProcessList.add("producer");
		my_premadeProcessList.add("ui");
		my_premadeProcessList.add("calculator");
		
	}	


	@Override
	public void keyTyped(final KeyEvent the_e) {
		
		KeyBoard kb = (KeyBoard) my_cpu.getKeyboard();
		kb.keyPressed();
		
		System.out.println("key typed");
	}


	@Override
	public void keyPressed(final KeyEvent the_e) {
		
		KeyBoard kb = (KeyBoard) my_cpu.getKeyboard();
		kb.keyPressed();
		
		System.out.println("key typed");
	}


	@Override
	public void keyReleased(final KeyEvent the_e) {
		
		KeyBoard kb = (KeyBoard) my_cpu.getKeyboard();
		kb.keyPressed();
		
		System.out.println("key typed");
	}
}
